package com.yvan.periscope;

import com.yvan.YvanUtil;
import com.yvan.periscope.stat.JvmStat;
import com.yvan.periscope.util.JvmUtils;
import com.yvan.platform.JsonWapper;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;

import java.lang.management.ManagementFactory;

/**
 * 作者： lzw<br/>
 * 创建时间：2018-08-27 17:19 <br/>
 */
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON, proxyMode = ScopedProxyMode.NO)
public class JvmCollectorService {

    private static final Logger LOG_JVM = LoggerFactory.getLogger("PER.JVM");

    @Value("${spring.application.name}")
    private String app;
    private final String server;

    public JvmCollectorService() {
        server = ManagementFactory.getRuntimeMXBean().getName().split("\\@")[1];
    }

    /**
     * 收集JVM状态数据
     */
    public synchronized void collect() {
        if (!LOG_JVM.isInfoEnabled()) {
            return;
        }
        final DateTime now = DateTime.now();
        JvmStat jvmStat = JvmUtils.getJvmStat();
        JsonWapper summary = new JsonWapper()
                .set("@timestamp", now.getMillis())
                .set("app", app)
                .set("server", server);
        // Thread
        if (jvmStat.getThreadCount() >= 0) {
            summary.set("threadCount", jvmStat.getThreadCount());
        }
        if (jvmStat.getThreadDeadlocks() >= 0) {
            summary.set("threadDeadlocks", jvmStat.getThreadDeadlocks());
        }
        if (jvmStat.getThreadBlockedCount() >= 0) {
            summary.set("threadBlockedCount", jvmStat.getThreadBlockedCount());
        }
        // GC - sum
        if (jvmStat.getPsScavengeCountSum() >= 0) {
            summary.set("psScavengeCountSum", jvmStat.getPsScavengeCountSum());
        }
        if (jvmStat.getPsScavengeTimeSum() >= 0) {
            summary.set("psScavengeTimeSum", jvmStat.getPsScavengeTimeSum());
        }
        if (jvmStat.getPsMarkSweepCountSum() >= 0) {
            summary.set("psMarkSweepCountSum", jvmStat.getPsMarkSweepCountSum());
        }
        if (jvmStat.getPsMarkSweepTimeSum() >= 0) {
            summary.set("psMarkSweepTimeSum", jvmStat.getPsMarkSweepTimeSum());
        }
        // GC - increment
        if (jvmStat.getPsScavengeCount() >= 0) {
            summary.set("psScavengeCount", jvmStat.getPsScavengeCount());
        }
        if (jvmStat.getPsScavengeTime() >= 0) {
            summary.set("psScavengeTime", jvmStat.getPsScavengeTime());
        }
        if (jvmStat.getPsMarkSweepCount() >= 0) {
            summary.set("psMarkSweepCount", jvmStat.getPsMarkSweepCount());
        }
        if (jvmStat.getPsMarkSweepTime() >= 0) {
            summary.set("psMarkSweepTime", jvmStat.getPsMarkSweepTime());
        }
        // Memory
        if (jvmStat.getMemoryTotalUsed() >= 0) {
            summary.set("memoryTotalUsed", jvmStat.getMemoryTotalUsed());
        }
        if (jvmStat.getMemoryTotalMax() >= 0) {
            summary.set("memoryTotalMax", jvmStat.getMemoryTotalMax());
        }
        if (jvmStat.getMemoryHeapUsed() >= 0) {
            summary.set("memoryHeapUsed", jvmStat.getMemoryHeapUsed());
        }
        if (jvmStat.getMemoryHeapMax() >= 0) {
            summary.set("memoryHeapMax", jvmStat.getMemoryHeapMax());
        }
        if (jvmStat.getMemoryNonHeapUsed() >= 0) {
            summary.set("memoryNonHeapUsed", jvmStat.getMemoryNonHeapUsed());
        }
        if (jvmStat.getMemoryNonHeapMax() >= 0) {
            summary.set("memoryNonHeapMax", jvmStat.getMemoryNonHeapMax());
        }
        if (jvmStat.getMemoryPoolsPsEdenSpaceMax() >= 0) {
            summary.set("memoryPoolsPsEdenSpaceMax", jvmStat.getMemoryPoolsPsEdenSpaceMax());
        }
        if (jvmStat.getMemoryPoolsPsEdenSpaceUsed() >= 0) {
            summary.set("memoryPoolsPsEdenSpaceUsed", jvmStat.getMemoryPoolsPsEdenSpaceUsed());
        }
        if (jvmStat.getMemoryPoolsPsOldGenMax() >= 0) {
            summary.set("memoryPoolsPsOldGenMax", jvmStat.getMemoryPoolsPsOldGenMax());
        }
        if (jvmStat.getMemoryPoolsPsOldGenUsed() >= 0) {
            summary.set("memoryPoolsPsOldGenUsed", jvmStat.getMemoryPoolsPsOldGenUsed());
        }
        LOG_JVM.info(YvanUtil.toJson(summary.getInnerMap()));
    }

//    public static void main(String[] args) {
//        JvmCollectorService service = new JvmCollectorService();
//        service.collect();
//        int count = 10000 * 10;
//        JvmStat jvmStat = null;
//        long start = System.nanoTime();
//        for (int i = 0; i < count; i++) {
//            jvmStat = JvmUtils.getJvmStat();
//        }
//        System.out.println((System.nanoTime() - start) / 1000000.0);
//        System.out.println(jvmStat);
//    }
}

